package com.jrx.anytxn.transaction.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.common.uitl.CollectorsUtils;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.common.uitl.SeqUtils;
import com.jrx.anytxn.customer.constant.CustomerConstant;
import com.jrx.anytxn.customer.entity.CmCustomerSecondLevel;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.i18n.response.TxnPage;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.entity.PrProductTable;
import com.jrx.anytxn.param.entity.TlFilePaymentLog;
import com.jrx.anytxn.param.service.product.IProductTableService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.redisson.service.RedissonLockService;
import com.jrx.anytxn.redisson.util.LockType;
import com.jrx.anytxn.ribbon.config.GrayVersionConfig;
import com.jrx.anytxn.transaction.bean.CalPayOffFeeBean;
import com.jrx.anytxn.transaction.bean.DebtBean;
import com.jrx.anytxn.transaction.bean.FilePaymentSaveBean;
import com.jrx.anytxn.transaction.bean.PaymentSaveBean;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.dto.payment.ThirdPartyPaymentRep;
import com.jrx.anytxn.transaction.dto.payment.ThirdPartyPaymentRes;
import com.jrx.anytxn.transaction.entity.*;
import com.jrx.anytxn.transaction.mapper.base.TlThirdPartyPaymentMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmLoanMainInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmRepaymentPlanInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlMistakeLogMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlThirdPartyPaymentMapper;
import com.jrx.anytxn.transaction.service.*;
import com.jrx.anytxn.transaction.utils.PaymentUtils;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class ThirdPartyPaymentServiceImpl implements IThirdPartyPaymentService {

    private static final Logger logger = LoggerFactory.getLogger(ThirdPartyPaymentServiceImpl.class);

    @Autowired
    private IProductTableService productTableService;
    @Autowired
    private ISegmentService segmentService;
    @Autowired
    private IRepaymentPlanService repaymentPlanService;
    @Autowired
    private IDebtCalculationService debtCalculationService;
    @Autowired
    private IFeeService feeService;
    @Resource
    private ExtAmRepaymentPlanInfoMapper extAmRepaymentPlanInfoMapper;
    @Resource
    private TlThirdPartyPaymentMapper tlThirdPartyPaymentMapper;
    @Autowired
    private IOrganizationTableService organizationTableService;
    @Resource
    private ExtTlMistakeLogMapper extTlMistakeLogMapper;
    @Resource
    private ExtTlThirdPartyPaymentMapper extTlThirdPartyPaymentMapper;
    @Autowired
    private IMistakeService mistakeService;
    @Resource
    private ExtAmLoanMainInfoMapper extAmLoanMainInfoMapper;
    @Autowired
    private IDealPaymentService dealPaymentService;
    @Autowired
    private RedissonLockService redissonLockService;
    @Autowired
    private GrayVersionConfig grayVersionConfig;
    @Autowired
    private ICustomerService customerService;

    @Override
    public TlThirdPartyPayment thirdPartyPay(ThirdPartyPaymentRep thirdPartyPaymentRep, Date bussinessDate, AmLoanMainInfo loanMainInfo, AmLoanAccountInfo loanAccountInfo) throws TxnBizException {
        //获取产品相关信息
        PrProductTable product = productTableService.findProByProIdAndOrgId(loanMainInfo.getProductId(),
                loanMainInfo.getOrganizationId(), loanMainInfo.getTenantId());

        //构建第三方还款信息
        TlThirdPartyPayment tlThirdPartyPayment = buildTlThirdPartyPayment(thirdPartyPaymentRep,bussinessDate,loanMainInfo,product);

        DebtBean debtBean = new DebtBean();
        List<AmRepaymentPlanInfo> repaymentPlanInfos = new ArrayList<>();
        AmRepaymentPlanInfo planInfo;

        switch (thirdPartyPaymentRep.getPaymentType()){
            case TransBizConstant.REPAYMENT_TYPE_PRETERMINTION ://提前结清
                repaymentPlanInfos = repaymentPlanService.getPlanList(loanMainInfo.getLoanId(),
                        loanMainInfo.getCustomerId(), loanMainInfo.getTenantId(),
                        Arrays.asList(TransBizConstant.LOAN_PLAN_STATUS_0, TransBizConstant.LOAN_PLAN_STATUS_1,
                                TransBizConstant.LOAN_PLAN_STATUS_2));
                //计算欠款
                debtBean = debtCalculationService.getBalance(loanAccountInfo, repaymentPlanInfos, bussinessDate, null, null, null, false);
                //获取因提前结清而产生的提前结清罚费，利息以及分期手续费
                CalPayOffFeeBean bean = feeService.getPayOffFeeAcct(loanMainInfo, loanAccountInfo, repaymentPlanInfos);
                BigDecimal debtAmt = debtBean.getTotalAmount();
                if(null != bean) {
                    //提前节结清罚费
                    BigDecimal payOffFeeAmt = bean.getPayOffFeeAmt();
                    //因提前结清而产生的分期手续费
                    BigDecimal installmentFee = bean.getInstallmentFeeSubBean().getTotalFeeAmt();
                    //因提前结清而产生的利息
                    BigDecimal intAmt = bean.getIntrSubBean().getTotalIntrAmt();
                    debtBean.setInterestAmount(debtBean.getInterestAmount().add(intAmt));
                    debtBean.setFeeAmount(debtBean.getFeeAmount().add(installmentFee));
                    debtAmt = debtBean.getTotalAmount().add(payOffFeeAmt).add(installmentFee).add(intAmt);
                }
                debtBean.setTotalAmount(debtAmt);
                break;
            case TransBizConstant.REPAYMENT_TYPE_CRT ://回购
                repaymentPlanInfos = repaymentPlanService.getPlanList(loanMainInfo.getLoanId(),
                        loanMainInfo.getCustomerId(), loanMainInfo.getTenantId(),
                        Arrays.asList(TransBizConstant.LOAN_PLAN_STATUS_0, TransBizConstant.LOAN_PLAN_STATUS_1,
                                TransBizConstant.LOAN_PLAN_STATUS_2));
                //计算欠款
                debtBean = debtCalculationService.getBalance(loanAccountInfo, repaymentPlanInfos, bussinessDate, null, null, null, false);
                break;
            case TransBizConstant.REPAYMENT_TYPE_OVERDUE : //逾期还款
                //欠款计算 获取欠款额
                debtBean = debtCalculationService.getBalance(loanAccountInfo, bussinessDate, true, null, null, false);
                break;
            case TransBizConstant.REPAYMENT_TYPE_PAY : //正常还款
                debtBean = debtCalculationService.getBalance(loanAccountInfo, bussinessDate, null, true, null, false);
                break;
            case TransBizConstant.REPAYMENT_TYPE_CMPS : //代偿
                planInfo = extAmRepaymentPlanInfoMapper.selectByLoanIdAndTenor(loanMainInfo.getCustomerId(),loanMainInfo.getTenantId(),
                        loanMainInfo.getChannel(),loanMainInfo.getLoanId(),thirdPartyPaymentRep.getPaymentTerm());

                repaymentPlanInfos.add(planInfo);
                if(TransBizConstant.LOAN_PLAN_STATUS_2.equals(planInfo.getPlanStatus())){
                    //欠款计算 获取欠款额
                    debtBean = debtCalculationService.getBalance(loanAccountInfo,repaymentPlanInfos, bussinessDate, true, null, null, false);
                }else{
                    debtBean = debtCalculationService.getBalance(loanAccountInfo,repaymentPlanInfos, bussinessDate, null, true, null, false);
                }
                break;
            case TransBizConstant.REPAYMENT_TYPE_PAY_TERM : //指定期次还款
                planInfo = extAmRepaymentPlanInfoMapper.selectByLoanIdAndTenor(loanMainInfo.getCustomerId(),loanMainInfo.getTenantId(),
                        loanMainInfo.getChannel(),loanMainInfo.getLoanId(),thirdPartyPaymentRep.getPaymentTerm());
                repaymentPlanInfos.add(planInfo);
                if(TransBizConstant.LOAN_PLAN_STATUS_2.equals(planInfo.getPlanStatus())){
                    //欠款计算 获取欠款额
                    debtBean = debtCalculationService.getBalance(loanAccountInfo,repaymentPlanInfos, bussinessDate, true, null, null, false);
                }else{
                    debtBean = debtCalculationService.getBalance(loanAccountInfo,repaymentPlanInfos, bussinessDate, null, true, null, false);
                }
                break;
            case TransBizConstant.REPAYMENT_TYPE_PREPAY_CURR : //提前还当期
                planInfo = extAmRepaymentPlanInfoMapper.selectByLoanIdAndTenor(loanMainInfo.getCustomerId(),loanMainInfo.getTenantId(),
                        loanMainInfo.getChannel(),loanMainInfo.getLoanId(),thirdPartyPaymentRep.getPaymentTerm());
                repaymentPlanInfos.add(planInfo);
                debtBean = debtCalculationService.getBalance(loanAccountInfo,repaymentPlanInfos, bussinessDate, null, null, null, false);
                break;
        }
        //金额校验
        if (debtBean.getTotalAmount().compareTo(BigDecimal.ZERO) <= 0) {
            String errMsg =
                    TxnRespCode.PAYMENT_DEBT_AMOUNT_ZERO.getFormatMsg(loanAccountInfo.getLoanId(), debtBean.getTotalAmount().toString());
            logger.error(errMsg);
            throw new TxnBizException(TxnRespCode.PAYMENT_DEBT_AMOUNT_ZERO.getCode(), TxnRespCode.PAYMENT_DEBT_AMOUNT_ZERO.getUserTips());
        }


        //保存
        tlThirdPartyPayment.setAmount(debtBean.getTotalAmount());
        tlThirdPartyPayment.setPrincipalAmount(debtBean.getPrincipalAmount());
        tlThirdPartyPayment.setInterestAmount(debtBean.getInterestAmount());
        tlThirdPartyPayment.setPenaltyAmount(debtBean.getPenaltyAmount());
        tlThirdPartyPayment.setCompoundAmount(debtBean.getCompountAmount());
        tlThirdPartyPayment.setFeeAmount(debtBean.getFeeAmount());

        tlThirdPartyPaymentMapper.insertSelective(tlThirdPartyPayment);

        return tlThirdPartyPayment;
    }

    @Override
    public void thirdPartyAllocation(TlThirdPartyPayment tlThirdPartyPayment) throws TxnBizException {
        //判断是否存在差错
        TlMistakeLog mistakeLog = extTlMistakeLogMapper.selectMistake(tlThirdPartyPayment.getSeqNo(), tlThirdPartyPayment.getCustomerId(),
                tlThirdPartyPayment.getTenantId(), TransBizConstant.MIS_STATUS_0);
        if (null != mistakeLog) {
            return;
        }

        Date bussinessDate = null;
        try {
            PrOrganizationTable organization =
                    organizationTableService.findByOrId(tlThirdPartyPayment.getOrganizationId(), tlThirdPartyPayment.getTenantId());
            bussinessDate = organization.getNextProcessingDate();
            this.dealAllocationByThirdParty(tlThirdPartyPayment, bussinessDate);
        } catch (Exception e) {
            //还款出现异常保存差错，后续进行差错处理
            logger.error("第三方还款分配发生异常", e);
            mistakeLog = mistakeService.buildMistakeLog(tlThirdPartyPayment, bussinessDate);
            extTlMistakeLogMapper.insertSelective(mistakeLog);
            return;
        }

        logger.info("更新第三方还款流水");
        TlThirdPartyPayment updateLog = new TlThirdPartyPayment();
        updateLog.setId(tlThirdPartyPayment.getId());
        updateLog.setCustomerId(tlThirdPartyPayment.getCustomerId());
        updateLog.setTenantId(tlThirdPartyPayment.getTenantId());
        updateLog.setSumStatus(TransBizConstant.PAYMENT_LOG_SUM_STATUS_S);
        extTlThirdPartyPaymentMapper.updateByIdAndCustomerIdAndTenantId(updateLog);

        logger.info("第三方还款分配结束");
    }

    @Override
    public void dealAllocationByThirdParty(TlThirdPartyPayment tlThirdPartyPayment, Date bussinessDate) throws Exception {
        logger.info("开始三方还款分配");

        List<AmLoanMainInfo> loanList = new ArrayList<>();

        AmLoanMainInfo loanMainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndCusId(tlThirdPartyPayment.getLoanId(),
                tlThirdPartyPayment.getCustomerId(), tlThirdPartyPayment.getTenantId());
        logger.info("订单，loanMainInfo:{}", loanMainInfo);
        loanList.add(loanMainInfo);

        TlPaymentLog tlPaymentLog = BeanMapping.copy(tlThirdPartyPayment,TlPaymentLog.class);
        tlPaymentLog.setAmount(tlThirdPartyPayment.getAmount());
        tlPaymentLog.setSeqNo(tlThirdPartyPayment.getSeqNo());
        tlPaymentLog.setPaymentType(tlThirdPartyPayment.getPaymentType());
        String lockKey = String.format(CustomerConstant.LOAN_REDIS_LOCK, tlPaymentLog.getTenantId(), tlPaymentLog.getCustomerId());
        logger.info("RedissionLock key:{}",lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(CustomerConstant.LOAN_REDIS_LOCK_WAITE_TIME,
                    CustomerConstant.LOAN_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}", lockKey, lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            String paymentType = tlThirdPartyPayment.getPaymentType();
            if (TransBizConstant.REPAYMENT_TYPE_PRETERMINTION.equals(paymentType)) {
                //提前结清
                dealPaymentService.dealPayOff(tlPaymentLog, loanList, bussinessDate);
            } else if (TransBizConstant.REPAYMENT_TYPE_OVERDUE.equals(paymentType)) {
                //逾期还款
                dealPaymentService.dealOverPay(tlPaymentLog, loanList, bussinessDate);
            } else if (TransBizConstant.REPAYMENT_TYPE_PAY.equals(paymentType)) {
                //正常还款
                dealPaymentService.dealPay(tlPaymentLog, loanList, bussinessDate);
            } else if (TransBizConstant.REPAYMENT_TYPE_CMPS.equals(paymentType)) {
                //代偿
                dealPaymentService.dealCmpsPay(tlPaymentLog, loanList, bussinessDate);
            } else if (TransBizConstant.REPAYMENT_TYPE_CRT.equals(paymentType)) {
                //回购
                dealPaymentService.dealCrtPay(tlPaymentLog, loanList, bussinessDate);
            } else if (TransBizConstant.REPAYMENT_TYPE_PREPAY_CURR.equals(paymentType)) {
                //提前还当期还款
                dealPaymentService.dealBillPrepayCurr(tlPaymentLog, loanList, bussinessDate);
            } else if (TransBizConstant.REPAYMENT_TYPE_PAY_TERM.equals(paymentType)) {
                //指定期次还款
                dealPaymentService.dealPay(tlPaymentLog, loanList, bussinessDate);
            }
        }finally {
            lock.unlock();
        }
    }

    private TlThirdPartyPayment buildTlThirdPartyPayment(ThirdPartyPaymentRep thirdPartyPaymentRep, Date bussinessDate, AmLoanMainInfo loanMainInfo,PrProductTable product) throws TxnBizException{
        TlThirdPartyPayment tlThirdPartyPayment = new TlThirdPartyPayment();
        try {
            tlThirdPartyPayment.setId(segmentService.getId(TransBizConstant.TL_THIRD_PARTY_PAYMENT_ID));
        } catch (SegmentException e) {
            logger.error("主键生成错误",e);
            throw new TxnBizException(TxnRespCode.ERROR.getUserTips());
        }
        tlThirdPartyPayment.setTenantId(loanMainInfo.getTenantId());
        tlThirdPartyPayment.setSeqNo(TransBizConstant.PAYMENT_LOG_SEQ_PREFIX+ SeqUtils.getSNByLength(TransBizConstant.PAYMENT_LOG_SEQ_RADOM_LENGTH));//流水号	唯一索引 PL+yyyyMMddHHmmssSSS +13位随机
        tlThirdPartyPayment.setPayId(thirdPartyPaymentRep.getSeqNo());
        tlThirdPartyPayment.setCustomerId(loanMainInfo.getCustomerId());//客户id	　
        tlThirdPartyPayment.setOrganizationId(loanMainInfo.getOrganizationId());//机构号
        tlThirdPartyPayment.setUserId(thirdPartyPaymentRep.getUserId());
        tlThirdPartyPayment.setChannel(loanMainInfo.getChannel());
        tlThirdPartyPayment.setProductId(loanMainInfo.getProductId());
        tlThirdPartyPayment.setLoanId(loanMainInfo.getLoanId());
        tlThirdPartyPayment.setPaymentType(thirdPartyPaymentRep.getPaymentType());//还款类型
        tlThirdPartyPayment.setPaymentTerm(thirdPartyPaymentRep.getPaymentTerm());
        tlThirdPartyPayment.setJointLoanFlag(loanMainInfo.getJointLoanFlag());
        tlThirdPartyPayment.setAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setPrincipalAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setInterestAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setPrincipalAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setCompoundAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setFeeAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setDescription(product.getChineseName()+ PaymentUtils.getPaymentTypeName(thirdPartyPaymentRep.getPaymentType()));
        tlThirdPartyPayment.setSumStatus(TransBizConstant.THIRD_PARTY_STATUS_T);
        tlThirdPartyPayment.setBusinessDate(bussinessDate);
        tlThirdPartyPayment.setCollateDate(bussinessDate);
        tlThirdPartyPayment.setUpdateBy(TransBizConstant.SYS_OPRATE);//操作员
        tlThirdPartyPayment.setRecordVersionNumber(TransBizConstant.INIT_RECORD_VERSION_NUMBER);
        tlThirdPartyPayment.setGrayVersion(grayVersionConfig.getCurrentVersion());
        return tlThirdPartyPayment;
    }

    @Override
    public TlThirdPartyPayment generateThirdLog(TlFilePaymentLog paymentLog, AmLoanAccountInfo loan, Date bussinessDate) throws TxnBizException {
        TlThirdPartyPayment tlThirdPartyPayment = new TlThirdPartyPayment();

        CmCustomerSecondLevel second = customerService.getSecondByChannelAndCustomerIdAndTensnId(loan.getChannel(),loan.getCustomerId(),loan.getTenantId(), loan.getProductId());

        try {
            tlThirdPartyPayment.setId(segmentService.getId(TransBizConstant.TL_THIRD_PARTY_PAYMENT_ID));
        } catch (SegmentException e) {
            logger.error("主键生成错误",e);
            throw new TxnBizException(TxnRespCode.ERROR.getUserTips());
        }

        tlThirdPartyPayment.setTenantId(loan.getTenantId());
        tlThirdPartyPayment.setSeqNo(TransBizConstant.PAYMENT_LOG_SEQ_PREFIX+ SeqUtils.getSNByLength(TransBizConstant.PAYMENT_LOG_SEQ_RADOM_LENGTH));//流水号	唯一索引 PL+yyyyMMddHHmmssSSS +13位随机
        tlThirdPartyPayment.setPayId(paymentLog.getTradeSeqNo());
        tlThirdPartyPayment.setCustomerId(loan.getCustomerId());//客户id	　
        tlThirdPartyPayment.setOrganizationId(loan.getOrganizationId());//机构号
        tlThirdPartyPayment.setUserId(second.getUserId());
        tlThirdPartyPayment.setChannel(loan.getChannel());
        tlThirdPartyPayment.setProductId(loan.getProductId());
        tlThirdPartyPayment.setLoanId(loan.getLoanId());
        String paymentType = "";
        if(TransBizConstant.FILE_TRADE_FLAG_1.equals(paymentLog.getTradeFlag())){
            paymentType = TransBizConstant.REPAYMENT_TYPE_PRETERMINTION;
        }else if(TransBizConstant.FILE_TRADE_FLAG_0.equals(paymentLog.getTradeFlag())){
            paymentType = TransBizConstant.REPAYMENT_TYPE_PAY;
        }else if(TransBizConstant.FILE_TRADE_FLAG_2.equals(paymentLog.getTradeFlag())){
            paymentType = TransBizConstant.REPAYMENT_TYPE_OVERDUE;
        }

        tlThirdPartyPayment.setPaymentType(paymentType);//还款类型
        tlThirdPartyPayment.setJointLoanFlag(TransBizConstant.JOINT_LOAN_FLAG_0);
        tlThirdPartyPayment.setAmount(paymentLog.getTradeAmt());
        tlThirdPartyPayment.setPrincipalAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setInterestAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setPrincipalAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setCompoundAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setPenaltyAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setFeeAmount(BigDecimal.ZERO);
        tlThirdPartyPayment.setDescription(PaymentUtils.getPaymentTypeName(paymentType));
        tlThirdPartyPayment.setSumStatus(TransBizConstant.THIRD_PARTY_STATUS_W);
        tlThirdPartyPayment.setBusinessDate(bussinessDate);
        tlThirdPartyPayment.setCollateDate(bussinessDate);
        tlThirdPartyPayment.setUpdateBy(TransBizConstant.SYS_OPRATE);//操作员
        tlThirdPartyPayment.setRecordVersionNumber(TransBizConstant.INIT_RECORD_VERSION_NUMBER);
        tlThirdPartyPayment.setGrayVersion(grayVersionConfig.getCurrentVersion());
        return tlThirdPartyPayment;
    }

    /**
     * 文件三方还款分配处理
     * @param filePaymentSaveBean
     * @param tlThirdPartyPayment
     * @throws TxnBizException
     */
    @Override
    public boolean fileThirdPartyAllocation(FilePaymentSaveBean filePaymentSaveBean, TlThirdPartyPayment tlThirdPartyPayment) throws TxnBizException {
        //判断是否存在差错
        TlMistakeLog mistakeLog = extTlMistakeLogMapper.selectMistake(tlThirdPartyPayment.getSeqNo(), tlThirdPartyPayment.getCustomerId(),
                tlThirdPartyPayment.getTenantId(), TransBizConstant.MIS_STATUS_0);
        if (null != mistakeLog) {
            return false;
        }

        Date bussinessDate = null;
        try {
            PrOrganizationTable organization =
                    organizationTableService.findByOrId(tlThirdPartyPayment.getOrganizationId(), tlThirdPartyPayment.getTenantId());
            bussinessDate = organization.getNextProcessingDate();
            PaymentSaveBean saveBean = this.dealAllocationByFileThirdParty(tlThirdPartyPayment, bussinessDate);
            filePaymentSaveBean.setPaymentSaveBean(saveBean);
        } catch (Exception e) {
            //还款出现异常保存差错，后续进行差错处理
            logger.error("第三方还款分配发生异常", e);
            mistakeLog = mistakeService.buildMistakeLog(tlThirdPartyPayment, bussinessDate);
            mistakeLog.setMisType(TransBizConstant.MIS_TYPE_7);
            filePaymentSaveBean.setMistakeLog(mistakeLog);
            return false;
        }

        logger.info("更新第三方还款流水");
        List<TlPaymentAllocationLog> list = filePaymentSaveBean.getPaymentSaveBean().getPaymentLogSaveList();
        Map<String,BigDecimal> allocationLogMap = list.stream()
                .collect(Collectors.groupingBy(TlPaymentAllocationLog::getConnectAccountType,
                        CollectorsUtils.summingBigDecimal(TlPaymentAllocationLog::getPostingAmount)));
        TlThirdPartyPayment updatePayment = new TlThirdPartyPayment();
        updatePayment.setId(tlThirdPartyPayment.getId());
        updatePayment.setSumStatus(TransBizConstant.PAYMENT_LOG_SUM_STATUS_S);
        updatePayment.setPrincipalAmount(Optional.ofNullable(allocationLogMap.get(TransBizConstant.ACCOUNT_TYPE_06)).orElse(BigDecimal.ZERO));
        updatePayment.setInterestAmount(Optional.ofNullable(allocationLogMap.get(TransBizConstant.ACCOUNT_TYPE_04)).orElse(BigDecimal.ZERO));
        updatePayment.setPenaltyAmount(Optional.ofNullable(allocationLogMap.get(TransBizConstant.ACCOUNT_TYPE_11)).orElse(BigDecimal.ZERO));
        updatePayment.setCompoundAmount(Optional.ofNullable(allocationLogMap.get(TransBizConstant.ACCOUNT_TYPE_12)).orElse(BigDecimal.ZERO));
        filePaymentSaveBean.setTlThirdPartyPayment(updatePayment);
        logger.info("第三方还款分配结束");
        return true;
    }

    /**
     * 文件分配冲账处理
     * @param tlThirdPartyPayment
     * @param bussinessDate
     * @return
     * @throws Exception
     */
    @Override
    public PaymentSaveBean dealAllocationByFileThirdParty(TlThirdPartyPayment tlThirdPartyPayment, Date bussinessDate) throws Exception {
        logger.info("开始三方还款分配");
        List<AmLoanMainInfo> loanList = new ArrayList<>();
        AmLoanMainInfo loanMainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndCusId(tlThirdPartyPayment.getLoanId(),
                tlThirdPartyPayment.getCustomerId(), tlThirdPartyPayment.getTenantId());
        logger.info("订单，loanMainInfo:{}", loanMainInfo);
        loanList.add(loanMainInfo);

        TlPaymentLog tlPaymentLog = BeanMapping.copy(tlThirdPartyPayment,TlPaymentLog.class);
        tlPaymentLog.setAmount(tlThirdPartyPayment.getAmount());
        tlPaymentLog.setSeqNo(tlThirdPartyPayment.getSeqNo());
        tlPaymentLog.setPaymentType(tlThirdPartyPayment.getPaymentType());
        String paymentType = tlThirdPartyPayment.getPaymentType();
        if (TransBizConstant.REPAYMENT_TYPE_PRETERMINTION.equals(paymentType)) {
            //提前结清
            return dealPaymentService.dealPayOffNotSave(tlPaymentLog, loanList, bussinessDate);
        } else if (TransBizConstant.REPAYMENT_TYPE_OVERDUE.equals(paymentType)) {
            //逾期还款
            return dealPaymentService.dealPayNotSave(tlPaymentLog, loanList, bussinessDate);
        } else if (TransBizConstant.REPAYMENT_TYPE_PAY.equals(paymentType)) {
            //正常还款
            return dealPaymentService.dealPayNotSave(tlPaymentLog, loanList, bussinessDate);
        }
        return null;
    }

    /**
     * 处理并保存文件还款分配信息
     * @param tlThirdPartyPayment
     * @param bussinessDate
     * @throws Exception
     */
    @Override
    public void dealAndSaveFilePayAllocate(TlThirdPartyPayment tlThirdPartyPayment, Date bussinessDate) throws Exception {
        PaymentSaveBean  saveBean = this.dealAllocationByFileThirdParty( tlThirdPartyPayment, bussinessDate);
        dealPaymentService.saveAllAccts(saveBean);
    }

    @Override
    public TxnPage<ThirdPartyPaymentRes> getThirdPartyPaymentWithPage(String channel, String customerId, String tenantId, Integer pageNum, Integer pageSize, String seqNo, String beginDate, String endDate) {
        Page<TlThirdPartyPayment> page = PageHelper.startPage(pageNum, pageSize);
        Date startTime = DateUtils.parseDate(beginDate, DateUtils.DATETIME_PATTERN);
        Date endTime = DateUtils.parseDate(endDate, DateUtils.DATETIME_PATTERN);
        List<TlThirdPartyPayment> tlThirdPartyPaymentList = extTlThirdPartyPaymentMapper.selectByCondSelectivePage(tenantId, channel, customerId, seqNo, startTime, endTime);
        List<ThirdPartyPaymentRes> res = BeanMapping.copyList(tlThirdPartyPaymentList, ThirdPartyPaymentRes.class);
        return new TxnPage<>(pageNum, pageSize, page.getTotal(), res);
    }

    @Override
    public ThirdPartyPaymentRes getThirdPartyPaymentBySeqNoAndCusId(String tenantId, String seqNo, String customerId) {
        TlThirdPartyPayment tlThirdPartyPayment = extTlThirdPartyPaymentMapper.selectThirdPartyPaymentBySeqNoAndCusId(tenantId, customerId, seqNo);
        ThirdPartyPaymentRes res = BeanMapping.copy(tlThirdPartyPayment, ThirdPartyPaymentRes.class);
        return res;
    }
}
